package com.michael.ims.gateway.webfilter;

import com.alibaba.fastjson.JSONObject;
import com.michael.ims.gateway.common.AccessDenyException;
import com.michael.ims.gateway.common.util.matcher.PathPatternParserServerWebExchangeMatcher;
import com.michael.ims.gateway.common.util.matcher.ServerWebExchangeMatcher;
import com.michael.ims.gateway.component.WebClientTemplate;
import com.michael.io.UserInfo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import static com.michael.ims.gateway.config.SystemConfig.CONTEXT_PATH;

/**
 * 访问控制
 */
@Order(400)
@Component
public class AccessControlWebFilter implements WebFilter {
    private final static ServerWebExchangeMatcher matchApi = new PathPatternParserServerWebExchangeMatcher(CONTEXT_PATH + "/**");
    private final static ServerWebExchangeMatcher matcherImsApp = new PathPatternParserServerWebExchangeMatcher(CONTEXT_PATH + "/ims-app/**");
    private final static ServerWebExchangeMatcher matcherLogin = new PathPatternParserServerWebExchangeMatcher(CONTEXT_PATH + "/login");

    @Autowired
    private WebClientTemplate webClientTemplate;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return matchApi.matches(exchange)
                .flatMap(apiMatch -> {
                    if (apiMatch.isMatch()) {
                        return matcherLogin.matches(exchange)
                                .flatMap(loginMatch -> {
                                    if (loginMatch.isMatch()) {
                                        return chain.filter(exchange);
                                    } else {
                                        return matcherImsApp.matches(exchange)
                                                .flatMap(imsAppMatch -> {
                                                    if (imsAppMatch.isMatch()) {
                                                        return chain.filter(exchange);
                                                    } else {
                                                        UserInfo userInfo = exchange.getAttribute("userInfo");
                                                        Long uid = userInfo.getId();
                                                        //匹配路径，判断是否属于哪个系统的
                                                        String fullPath = exchange.getRequest().getURI().getPath();
                                                        return this.validateRights(fullPath, uid).flatMap(flag -> {
                                                            if (flag)
                                                                return chain.filter(exchange);
                                                            else
                                                                return Mono.error(new AccessDenyException("无权限访问"));
                                                        });
                                                    }
                                                });
                                    }
                                });
                    } else
                        return chain.filter(exchange);
                });
    }

    public Mono<Boolean> validateRights(String fullPath, Long uid) {
        ValidateRightReq req = new ValidateRightReq();
        req.setFullPath(fullPath);
        req.setUid(uid);
        return webClientTemplate.handle("/rights/validate", req, Boolean.class);
    }

    @Setter
    @Getter
    private class ValidateRightReq {
        private Long uid;
        private String fullPath;
    }
}
